Skip to content

fix: add TTY detection before TUI fallbacks to prevent agent/CI hangs#949

Merged
jesseturner21 merged 2 commits intomainfrom
fix/tty-detection-685
Apr 24, 2026
Merged

fix: add TTY detection before TUI fallbacks to prevent agent/CI hangs#949
jesseturner21 merged 2 commits intomainfrom
fix/tty-detection-685

Conversation

@jesseturner21
Copy link
Copy Markdown
Contributor

@jesseturner21 jesseturner21 commented Apr 24, 2026

Problem

When agentcore commands are invoked without flags in a non-interactive environment (CI, piped stdin, agent automation), the CLI falls through to Ink TUI rendering. Without a TTY attached, the process hangs indefinitely because there is no terminal to interact with — the only recovery is a timeout or SIGKILL.

Reproduction:

echo "" | agentcore create
# Process hangs forever

Fix

Add a requireTTY() guard function that checks process.stdout.isTTY before launching any Ink TUI flow. When no TTY is detected and no CLI-mode flags are present, the CLI prints a clear error message and exits with code 1:

Error: This command requires an interactive terminal. Use --help to see non-interactive flags.

The guard is applied at all 17 TUI entry points:

  • Bare agentcore (fullscreen TUI)
  • create, deploy, invoke, dev --no-browser, add, remove commands
  • All primitive add/remove TUI fallbacks (agent, memory, credential, evaluator, online-eval, gateway, gateway-target, policy-engine, policy)

CLI-mode paths (flag-based invocation) are completely unaffected — agentcore create --name myproject --defaults --json continues to work in non-TTY environments.

Test plan

  • echo "" | agentcore — prints error + exits 1 (was: hang)
  • echo "" | agentcore create — prints error + exits 1 (was: hang)
  • echo "" | agentcore deploy — prints error + exits 1 (was: hang)
  • echo "" | agentcore add — prints error + exits 1 (was: hang)
  • echo "" | agentcore remove — prints error + exits 1 (was: hang)
  • echo "" | agentcore invoke — prints error + exits 1 (was: hang)
  • echo "" | agentcore create --name test --defaults --dry-run --json — still works (CLI mode unaffected)
  • All 3406 unit tests pass

Closes #685

When commands are invoked without flags in non-interactive environments
(CI, piped stdin, agent automation), the CLI falls through to Ink TUI
rendering which hangs indefinitely. Add a requireTTY() guard at every
TUI entry point that checks process.stdout.isTTY and exits with a
helpful error message directing users to --help for non-interactive flags.

Closes #685
@jesseturner21 jesseturner21 requested a review from a team April 24, 2026 17:46
@github-actions github-actions Bot added the size/s PR size: S label Apr 24, 2026
@github-actions github-actions Bot added the agentcore-harness-reviewing AgentCore Harness review in progress label Apr 24, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Package Tarball

aws-agentcore-0.10.0.tgz

How to install

npm install https://github.com/aws/agentcore-cli/releases/download/pr-949-tarball/aws-agentcore-0.10.0.tgz

@jesseturner21
Copy link
Copy Markdown
Contributor Author

The guard checks process.stdout.isTTY, but the hang described in #685 is caused by stdin not being a TTY, not stdout. Ink's TUI reads keyboard input from process.stdin — when stdin is piped, Ink can't read input and the process hangs. Stdout being redirected doesn't cause the hang.

This is observable in the PR's own test plan. For echo "" | agentcore create:

  • process.stdin.isTTYundefined (stdin is a pipe) ← this is what causes the hang
  • process.stdout.isTTYtrue (stdout is still the terminal)

So requireTTY() as written will not trigger for the exact reproduction case in #685 (echo "" | agentcore create). It will only trigger when stdout is redirected (e.g. agentcore create > out.txt), which wasn't the reported bug, and it will incorrectly block users who just want to capture TUI ANSI output to a file (a minor edge case, but not the failure mode we want to guard).

CI/agent environments typically have both streams non-TTY, so the check happens to fire there, but the behavior on an interactive terminal with piped stdin (the canonical repro) is unchanged.

Options to fix:

  1. Check process.stdin.isTTY instead of process.stdout.isTTY. This matches the actual failure mode and matches what tools like git do for interactive prompts.
  2. Check both — fail if either is non-TTY. Slightly more conservative; catches stdin-piped, stdout-redirected, and CI scenarios uniformly.
  3. Check process.stdin.isTTY && process.stdout.isTTY with a clearer error message that distinguishes the two cases.

Option 1 or 2 is probably what you want. It would also be worth actually running the test-plan commands against the built CLI (not just npm test) before merging, since the npm test suite doesn't appear to include coverage for the new guard and wouldn't catch this.

@github-actions github-actions Bot removed the agentcore-harness-reviewing AgentCore Harness review in progress label Apr 24, 2026
The hang from #685 is caused by stdin not being a TTY (Ink reads
keyboard input from stdin), not stdout. Check both stdin and stdout
so the guard fires for piped stdin, redirected stdout, and CI
environments where both are non-TTY.
@github-actions github-actions Bot added size/s PR size: S and removed size/s PR size: S labels Apr 24, 2026
@jesseturner21
Copy link
Copy Markdown
Contributor Author

Good catch — fixed in 03d3b3f. The guard now checks both process.stdin.isTTY and process.stdout.isTTY (option 2 from your comment). Either being non-TTY will trigger the error since Ink needs stdin for keyboard input and stdout for rendering.

Verified with the updated bundle:

  • echo "" | agentcore create → error + exit 1 (stdin piped, stdout is terminal)
  • echo "" | agentcore create --name myproj --defaults --dry-run --json → still works (CLI mode unaffected)

@github-actions
Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 42% 7247 / 17254
🔵 Statements 41.41% 7680 / 18543
🔵 Functions 40.14% 1286 / 3203
🔵 Branches 40.47% 4825 / 11920
Generated in workflow #1935 for commit 03d3b3f by the Vitest Coverage Report Action

@jesseturner21 jesseturner21 merged commit c30ed54 into main Apr 24, 2026
23 checks passed
@jesseturner21 jesseturner21 deleted the fix/tty-detection-685 branch April 24, 2026 19:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s PR size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add TTY detection before TUI fallbacks to prevent agent/CI hangs

2 participants